<?xml version="1.0" encoding="utf-8"?>

<!--
Licensed to the .NET Foundation under one or more agreements.
The .NET Foundation licenses this file to you under the MIT license.
-->

<!--
Visual Studio debugger visualizers for RyuJIT.

Documentation for VS natvis format: https://learn.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2022
Documentation for VS debugger format specifiers: https://learn.microsoft.com/en-us/visualstudio/debugger/format-specifiers-in-cpp?view=vs-2022
-->

<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

  <Type Name="Compiler">
    <DisplayString>[{info.compFullName,sb} ({info.compMethodHashPrivate,x})]</DisplayString>
    <StringView>info.compFullName,sb</StringView>
  </Type>

  <Type Name="BasicBlock">
    <DisplayString Condition="bbKind==BBJ_COND || bbKind==BBJ_ALWAYS || bbKind==BBJ_LEAVE || bbKind==BBJ_EHCATCHRET || bbKind==BBJ_CALLFINALLY || bbKind==BBJ_CALLFINALLYRET || bbKind==BBJ_EHFILTERRET">BB{bbNum,d}->BB{bbTargetEdge->m_destBlock->bbNum,d}; {bbKind,en}</DisplayString>
    <DisplayString Condition="bbKind==BBJ_SWITCH">BB{bbNum,d}; {bbKind,en}; {bbSwtTargets->bbsCount} cases</DisplayString>
    <DisplayString Condition="bbKind==BBJ_EHFINALLYRET">BB{bbNum,d}; {bbKind,en}; {bbEhfTargets->bbeCount} succs</DisplayString>
    <DisplayString>BB{bbNum,d}; {bbKind,en}</DisplayString>
  </Type>

  <Type Name="FlowEdge">
    <DisplayString Condition="m_dupCount!=1">BB{m_sourceBlock->bbNum,d}->BB{m_destBlock->bbNum,d} ({m_likelihood,g}) (dup {m_dupCount,d})</DisplayString>
    <DisplayString>BB{m_sourceBlock->bbNum,d}->BB{m_destBlock->bbNum,d} ({m_likelihood,g})</DisplayString>
  </Type>

  <Type Name="Compiler::LoopDsc">
    <DisplayString Condition="lpFlags &amp; LPFLG_REMOVED">REMOVED</DisplayString>
    <DisplayString Condition="lpFlags &amp; LPFLG_HAS_PREHEAD">[BB{lpTop->bbNum,d}..BB{lpBottom->bbNum,d}] pre-h:BB{lpHead->bbNum,d} e:BB{lpEntry->bbNum,d} {lpFlags,en}</DisplayString>
    <DisplayString>[BB{lpTop->bbNum,d}..BB{lpBottom->bbNum,d}] h:BB{lpHead->bbNum,d} e:BB{lpEntry->bbNum,d} {lpFlags,en}</DisplayString>
  </Type>

  <Type Name="EHblkDsc">
    <DisplayString>type={ebdHandlerType}</DisplayString>
  </Type>

  <!-- GenTree -->

  <Type Name="GenTree">
    <DisplayString>{gtTreeID, d}: [{gtOper,en}, {gtType,en}]</DisplayString>
  </Type>
  <Type Name="GenTreeIntCon">
    <DisplayString>{gtTreeID, d}: [IntCon={((GenTreeIntCon*)this)-&gt;gtIconVal, d}]</DisplayString>
  </Type>
  <Type Name="GenTreeDblCon">
    <DisplayString>{gtTreeID, d}: [DblCon={((GenTreeDblCon*)this)-&gt;gtDconVal, g}]</DisplayString>
  </Type>
  <Type Name="GenTreeStrCon">
    <DisplayString>CNS_STR</DisplayString>
  </Type>
  <Type Name="GenTreeVecCon">
    <DisplayString>CNS_VEC</DisplayString>
  </Type>
  <Type Name="GenTreeLngCon">
    <DisplayString>{gtTreeID, d}: [LngCon={((GenTreeLngCon*)this)-&gt;gtLconVal, l}]</DisplayString>
  </Type>
  <Type Name="GenTreeOp">
    <DisplayString Condition="this->gtOper==GT_CAST">{gtTreeID, d}: [{((GenTreeCast*)this)-&gt;gtCastType,en} &lt;- {((GenTreeUnOp*)this)-&gt;gtOp1-&gt;gtType,en}]</DisplayString>
    <DisplayString Condition="this->gtOper==GT_HWINTRINSIC">{gtTreeID, d}: [{((GenTreeHWIntrinsic*)this)-&gt;gtHWIntrinsicId,en}, {gtType,en}]</DisplayString>
    <DisplayString>{gtTreeID, d}: [{gtOper,en}, {gtType,en}]</DisplayString>
  </Type>

  <Type Name="Statement">
    <Expand>
      <LinkedListItems>
        <HeadPointer>this-&gt;m_treeList</HeadPointer>
        <NextPointer>this-&gt;gtNext</NextPointer>
        <ValueNode>this</ValueNode>
      </LinkedListItems>
    </Expand>
  </Type>

  <Type Name="LclVarDsc">
    <DisplayString Condition="lvReason==0">[V{lvSlotNum,d}: {lvType,en}]</DisplayString>
    <DisplayString>[V{lvSlotNum,d}: {lvType,en}-{lvReason,s}]</DisplayString>
  </Type>

  <Type Name="GenTreeLclVar" Inheritable="false">
    <DisplayString>{gtTreeID, d}: [{gtOper,en}, {gtType,en} V{((GenTreeLclVar*)this)-&gt;_gtLclNum,u}]</DisplayString>
  </Type>

  <Type Name="GenTreeLclFld" Inheritable="false">
    <DisplayString>{gtTreeID, d}: [{gtOper,en}, {gtType,en} V{((GenTreeLclFld*)this)-&gt;_gtLclNum,u}[+{((GenTreeLclFld*)this)-&gt;m_lclOffs,u}]]</DisplayString>
  </Type>

  <!-- Scalar evolution -->
  <Type Name="Scev">
    <DisplayString>[{Oper,en}, {Type,en}]</DisplayString>
  </Type>

  <!-- Register allocation -->
  <Type Name="LinearScan">
    <DisplayString>LinearScan</DisplayString>
    <Expand>
        <Item Name="inVarToRegMaps">"InVarToRegMaps"</Item>
        <CustomListItems>
          <Variable Name="block" InitialValue="this-&gt;compiler-&gt;fgFirstBB" />
          <Variable Name="bbLiveInMap" InitialValue="block ? block->bbLiveIn[0] : 0" />
          <Variable Name="inVarMap" InitialValue="block ? this->inVarToRegMaps[block->bbNum] : 0" />
          <Variable Name="varIndex" InitialValue="0" />
          <Loop Condition="block">
              <Item Name="---BB{block->bbNum,2u}---">block->bbNum,2u</Item>
              <Exec>varIndex = 0</Exec>
              <Exec>inVarMap = this->inVarToRegMaps[block->bbNum]</Exec>
              <Exec>bbLiveInMap = block->bbLiveIn[0]</Exec>
              <Loop Condition="bbLiveInMap != 0">
                <Item Name="V{this->localVarIntervals[varIndex]->varNum,2u}" Condition="(bbLiveInMap &amp; 1) != 0">((regNumber)inVarMap[varIndex]),en</Item>
                <Exec>varIndex++</Exec>
                <Exec>bbLiveInMap = bbLiveInMap >> 1</Exec>
              </Loop>
            <Exec>block = block->Next()</Exec>
          </Loop>
        </CustomListItems>
        <Item Name="outVarToRegMaps">"OutVarToRegMaps"</Item>
        <CustomListItems>
          <Variable Name="block" InitialValue="this-&gt;compiler-&gt;fgFirstBB" />
          <Variable Name="bbLiveInMap" InitialValue="block ? block->bbLiveIn[0] : 0" />
          <Variable Name="outVarMap" InitialValue="block ? this->outVarToRegMaps[block->bbNum] : 0" />
          <Variable Name="varIndex" InitialValue="0" />
          <Loop Condition="block">
              <Item Name="---BB{block->bbNum,2u}---">block->bbNum,2u</Item>
              <Exec>varIndex = 0</Exec>
              <Exec>outVarMap = this->outVarToRegMaps[block->bbNum]</Exec>
              <Exec>bbLiveInMap = block->bbLiveIn[0]</Exec>
              <Loop Condition="bbLiveInMap != 0">
                <Item Name="V{this->localVarIntervals[varIndex]->varNum,2u}" Condition="(bbLiveInMap &amp; 1) != 0">((regNumber)outVarMap[varIndex]),en</Item>
                <Exec>varIndex++</Exec>
                <Exec>bbLiveInMap = bbLiveInMap >> 1</Exec>
              </Loop>
            <Exec>block = block->Next()</Exec>
          </Loop>
        </CustomListItems>
        <Item Name="AvailableRegs mask">this-&gt;m_AvailableRegs</Item>
        <CustomListItems>
          <Variable Name="reg" InitialValue="this->m_AvailableRegs" />
          <Variable Name="regIndex" InitialValue="0" />
          <Loop Condition="reg != 0">
            <Item Condition="(reg &amp; 1) != 0">((regNumber)regIndex),en</Item>
            <Exec>regIndex++</Exec>
            <Exec>reg = reg >> 1</Exec>
          </Loop>
        </CustomListItems>
        <Item Name="RegistersWithConstants mask">this-&gt;m_RegistersWithConstants</Item>
        <CustomListItems>
          <Variable Name="reg" InitialValue="this->m_RegistersWithConstants" />
          <Variable Name="regIndex" InitialValue="0" />
          <Loop Condition="reg != 0">
            <Item Condition="(reg &amp; 1) != 0">((regNumber)regIndex),en</Item>
            <Exec>regIndex++</Exec>
            <Exec>reg = reg >> 1</Exec>
          </Loop>
        </CustomListItems>
    </Expand>
  </Type>

  <Type Name="RefPosition">
    <DisplayString>[#{rpNum,d} - {refType,en}]</DisplayString>
    <Expand>
        <Item Name="Referent" Condition="this->isPhysRegRef">(RegRecord*)this-&gt;referent</Item>
        <Item Name="Referent" Condition="!this->isPhysRegRef">(Interval*)this-&gt;referent</Item>
        <CustomListItems>
          <Variable Name="reg" InitialValue="this->registerAssignment" />
          <Variable Name="regIndex" InitialValue="0" />
          <Loop Condition="reg != 0">
            <Item Condition="(reg &amp; 1) != 0">((regNumber)regIndex),en</Item>
            <Exec>regIndex++</Exec>
            <Exec>reg = reg >> 1</Exec>
          </Loop>
        </CustomListItems>
    </Expand>
  </Type>

  <Type Name="Interval">
    <DisplayString Condition="this->isUpperVector">[U{this->relatedInterval->varNum,d}, #{this->intervalIndex, d}, reg={(regNumber)physReg, en}]</DisplayString>
    <DisplayString Condition="this->isLocalVar">[V{this->varNum,d}, #{this->intervalIndex, d}, reg={(regNumber)physReg, en}]</DisplayString>
    <DisplayString Condition="this->isConstant">[C{this->intervalIndex, d}, reg={(regNumber)physReg, en}]</DisplayString>
    <DisplayString>[I{this->intervalIndex, d}, reg={(regNumber)physReg, en}]</DisplayString>
  </Type>

  <Type Name="RegRecord">
    <DisplayString>[reg={((regNumber)regNum),en}, type={registerType, en}]</DisplayString>
    <Expand>
      <Item Name="[Assigned]">assignedInterval</Item>
      <Item Name="[Previous]">previousInterval</Item>
    </Expand>
  </Type>

  <!-- Emitter -->
  <Type Name="insGroup">
    <DisplayString Condition="igFlags &amp; 0x200">IG{igNum,d}, size={igSize,d}, offset={igOffs,d} [extend]</DisplayString>
    <DisplayString>IG{igNum,d}, size={igSize,d}, offset={igOffs,d}</DisplayString>
  </Type>

  <Type Name="emitter::instrDesc">
    <DisplayString Condition="(_idInsFmt == IF_RRD) || (_idInsFmt == IF_RWR) || (_idInsFmt == IF_RRW)">{_idIns,en} {_idReg1,en}</DisplayString>
    <DisplayString Condition="(_idInsFmt == IF_RRD_CNS) || (_idInsFmt == IF_RWR_CNS) || (_idInsFmt == IF_RRW_CNS)">{_idIns,en} {_idReg1,en}, {_idLargeCns,d}</DisplayString>
    <DisplayString Condition="(_idInsFmt == IF_RRW_SHF) &amp;&amp; (_idLargeCns != 0)">{_idIns,en} {_idReg1,en}, {_idLargeCns,d}</DisplayString>
    <DisplayString Condition="(_idInsFmt == IF_RRW_SHF) &amp;&amp; (_idLargeCns == 0)">{_idIns,en} {_idReg1,en}, {_idSmallCns,d}</DisplayString>
    <DisplayString>{_idIns,en}</DisplayString>
  </Type>

  <!-- utils -->
   <Type Name="jitstd::list&lt;*&gt;">
    <DisplayString Condition="m_nSize > 0">Size={m_nSize}</DisplayString>
    <DisplayString Condition="m_nSize == 0">Empty</DisplayString>
    <Expand>
      <LinkedListItems>
        <Size>m_nSize</Size>
        <HeadPointer>this->m_pHead</HeadPointer>
        <NextPointer>this-&gt;m_pNext</NextPointer>
        <ValueNode>this-&gt;m_value</ValueNode>
      </LinkedListItems>
    </Expand>
  </Type>

  <Type Name="jitstd::vector&lt;*&gt;">
    <DisplayString Condition="m_nSize > 0">size={m_nSize,d} capacity={m_nCapacity,d}</DisplayString>
    <DisplayString Condition="m_nSize == 0">Empty</DisplayString>
    <Expand>
      <ArrayItems>
        <Size>m_nSize</Size>
        <ValuePointer>m_pArray</ValuePointer>
      </ArrayItems>
    </Expand>
  </Type>

  <Type Name="JitExpandArray&lt;*&gt;">
    <DisplayString Condition="m_size > 0">size={m_size,d}</DisplayString>
    <DisplayString Condition="m_size == 0">Empty</DisplayString>
    <Expand>
      <ArrayItems>
        <Size>m_size</Size>
        <ValuePointer>m_members</ValuePointer>
      </ArrayItems>
    </Expand>
  </Type>

  <Type Name="JitExpandArrayStack&lt;*&gt;">
    <DisplayString Condition="m_size > 0">size={m_size,d} used={m_used,d}</DisplayString>
    <DisplayString Condition="m_size == 0">Empty</DisplayString>
    <Expand>
      <ArrayItems>
        <Size>m_used</Size>
        <ValuePointer>m_members</ValuePointer>
      </ArrayItems>
    </Expand>
  </Type>

  <!-- Loop cloning -->

  <!-- LcOptInfo is really one of its derived types, so figure out which one. Set Inheritable=false to prevent recursion. -->
  <Type Name="LcOptInfo" Inheritable="false">
    <DisplayString>{optType,en}</DisplayString>
    <Expand>
      <ExpandedItem Condition="optType == LcOptInfo::OptType::LcJaggedArray">(LcJaggedArrayOptInfo*)this,nd</ExpandedItem>
      <ExpandedItem Condition="optType == LcOptInfo::OptType::LcMdArray">(LcMdArrayOptInfo*)this,nd</ExpandedItem>
    </Expand>
  </Type>

</AutoVisualizer>
